﻿package src.uipackage.ui {
	
	import com.onebyonedesign.ui.events.ColorEvent;
	import com.onebyonedesign.ui.graphics.EyeDropperGraphic;
	import flash.display.BitmapData;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;
	import flash.ui.Mouse;
	
	/**
	* UI widget that allows users to select color from a specified image (inside Sprite or MovieClip).
	* @author Devon O.
	*/
	public class OBO_EyeDropper extends Sprite {
		
		private var _target:DisplayObjectContainer;
		private var _targetData:BitmapData;
		private var _w:Number;
		private var _h:Number;
		private var _currentColor:uint;
		private var _displaySwatch:Sprite;
		private var _dropper:EyeDropperGraphic;
		private var _cxf:ColorTransform = new ColorTransform();
		
		/**
		 * 
		 * The OBO_EyeDropper is a UI widget which allows users to select a color from a specified image contained inside a Sprite or MovieClip.
		 * Once a color has been selected, the OBO_EyeDropper instance dispatches a ColorEvent.COLOR_SELECT event.
		 * 
		 * @example The following example creates a new OBO_EyeDropper instance which allows the user to select a color from a MovieClip contained within the project's .fla library.
		 * <listing version="3.0">
		 *	 private function initEyeDropper():void {
		 *		// "Pic" is a linked MovieClip within the .fla library
		 *		var eyeDropperPic:Pic = new Pic();
		 *		eyeDropperPic.x = 100;
		 *		eyeDropperPic.y = 50;
		 *		addChild(eyeDropperPic);
		 *		
		 *		var _eyeDropper:OBO_EyeDropper = new OBO_EyeDropper(eyeDropperPic);
		 *		_eyeDropper.x = 50;
		 *		_eyeDropper.y = 50;
		 *		_eyeDropper.addEventListener(ColorEvent.COLOR_SELECT, onEyeDropperSelect);
		 *		addChild(_eyeDropper);
		 *	}
		 *	
		 *	private function onEyeDropperSelect(ce:ColorEvent):void {
		 *		trace (ce.color);
		 *		trace (ce.colorString);
		 *	}
		 * </listing>
		 * 
		 * @param	target			The Sprite or MovieClip instance which will act as the user's color palette.
		 * @param	width			The width of the "display swatch."
		 * @param	height			The height of the "display swatch."
		 * @param	defaultColor	The color originally shown by the "display swatch."
		 * 
		 * @see		OBO_ColorPicker
		 */
		
		public function OBO_EyeDropper(target:DisplayObjectContainer, width:Number = 25, height:Number = 25, defaultColor:uint = 0x000000):void {
			_w = width;
			_h = height;
			_currentColor = defaultColor;
			_target = target;
			
			init();
		}
		
		private function init():void {
			_targetData = new BitmapData(_target.width, _target.height);
			_targetData.draw(_target);
			createDropper();
			createDisplaySwatch();
		}
		
		private function createDropper():void {
			_dropper = new EyeDropperGraphic();
		}
		
		private function createDisplaySwatch():void {
			_displaySwatch = new Sprite();
			_displaySwatch.graphics.beginFill(_currentColor);
			_displaySwatch.graphics.drawRect(0, 0, _w, _h);
			_displaySwatch.graphics.endFill();
			_displaySwatch.buttonMode = true;
			_displaySwatch.addEventListener(MouseEvent.CLICK, startDropper);
			addChild(_displaySwatch);
		}
		
		private function startDropper(me:MouseEvent):void {
			me.stopImmediatePropagation();
			Mouse.hide();
			_target.addEventListener(MouseEvent.CLICK, stopDropper);
			_target.stage.addEventListener(MouseEvent.CLICK, stopDropper);
			_target.stage.addEventListener(Event.MOUSE_LEAVE, stopDropper);
			_displaySwatch.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
			_dropper.x = mouseX;
			_dropper.y = mouseY - 16;
			parent.setChildIndex(this, parent.numChildren - 1);
			addChild(_dropper);
			_displaySwatch.mouseEnabled = false;
		}
		
		private function stopDropper(me:Event):void {
			me.stopImmediatePropagation();
			Mouse.show();
			removeChild(_dropper);
			_target.removeEventListener(MouseEvent.CLICK, stopDropper);
			_target.stage.removeEventListener(MouseEvent.CLICK, stopDropper);
			_target.stage.removeEventListener(Event.MOUSE_LEAVE, stopDropper);
			_displaySwatch.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
			
			if (me.currentTarget == _target) {
				_currentColor = _targetData.getPixel(_target.mouseX, _target.mouseY);
				dispatchEvent(new ColorEvent(ColorEvent.COLOR_SELECT, _currentColor, colorString()));
			}
			_cxf.color = _currentColor;
			_displaySwatch.transform.colorTransform = _cxf;
			_displaySwatch.mouseEnabled = true;
		}
		
		private function colorString():String {
			var col:String = _currentColor.toString(16);
			var colArray:Array = col.split("");
			var len:Number = colArray.length;
			if (len < 6) {
				for (var i:int = len; i < 6; i++) {
					colArray.unshift("0"); 
				}
			}
			return colArray.join("").toUpperCase();
		}
		
		private function onMove(me:MouseEvent):void {
			_dropper.x = mouseX;
			_dropper.y = mouseY - 16;
			if (_target.hitTestPoint(stage.mouseX, stage.mouseY)) {
				_cxf.color = _targetData.getPixel(_target.mouseX, _target.mouseY);
				_displaySwatch.transform.colorTransform = _cxf;
			}
			me.updateAfterEvent();
		}
	}
}